Bài học Scratch cho học sinh THCS

Vòng lặp nâng cao và tối ưu thuật toán đơn giản

Khám phá cách dùng vòng lặp thông minh hơn, giảm thao tác thừa và giúp dự án Scratch chạy mượt hơn — ngay cả khi bạn mới bắt đầu học tư duy thuật toán.

Vòng lặp là gì và vì sao cần học sâu hơn?

Bạn đã biết các khối lặp lại (repeat), lặp mãi (forever) trong nhóm Điều khiển. Đó là cách máy tính thực hiện một việc nhiều lần mà không cần kéo thả hàng chục khối giống nhau.

Nhóm khối Điều khiển trong Scratch
Nhóm Điều khiển (màu cam) chứa các khối vòng lặp và điều kiện

Ở mức nâng cao, ta không chỉ hỏi "lặp bao nhiêu lần?" mà còn hỏi: lặp đến khi nào thì dừng, lồng vòng lặp ra sao cho hợp lý, và làm sao để máy tính làm ít việc thừa nhất. Đây chính là bước đầu của tối ưu thuật toán — tìm cách giải quyết vấn đề nhanh hơn, gọn hơn và ít tốn tài nguyên hơn.

💡 Ghi nhớ

Thuật toán tối ưu không có nghĩa là "khó hiểu". Ở cấp THCS, tối ưu thường đơn giản là: bớt lặp thừa, tính trước những gì không đổi, và tránh các khối nặng bên trong vòng lặp.

Ba kiểu vòng lặp cần nắm vững

Scratch cung cấp ba cách lặp chính. Mỗi kiểu phù hợp với một tình huống khác nhau:

Lặp lại (repeat) Biết trước số lần lặp — ví dụ vẽ 6 cạnh lục giác
Lặp mãi (forever) Chạy liên tục — phù hợp game, điều khiển nhân vật
Lặp đến khi (repeat until) Dừng khi điều kiện đúng — linh hoạt nhất

Khối "lặp đến khi" — công cụ mạnh nhất

Khối repeat until <điều kiện> lặp các lệnh bên trong cho đến khi điều kiện trở thành đúng (true), rồi thoát vòng lặp. Nó giống câu "cứ làm đi, đến khi xong thì dừng".

khi nhấn phím [space]
  lặp đến khi <chạm [cạnh v]?>
    tiến [5] bước
  kết thúc

Nhân vật sẽ tiến từng bước cho đến khi chạm cạnh sân khấu. Bạn không cần đoán trước phải lặp bao nhiêu lần — điều kiện tự quyết định.

📌 Ví dụ: Đếm ngược

Đặt biến đếm = 10. Dùng lặp đến khi với điều kiện đếm = 0. Mỗi vòng: giảm đếm đi 1 và nói giá trị biến. Khi về 0, vòng lặp dừng và bạn có thể phát âm thanh "Bắt đầu!".

💡 Ghi nhớ

Điều kiện trong repeat until là điều kiện dừng, không phải điều kiện tiếp tục. Nếu muốn "lặp khi còn sống", hãy viết "lặp đến khi không còn sống".

Vòng lặp lồng nhau

Khi đặt một vòng lặp bên trong vòng lặp khác, ta gọi là vòng lặp lồng nhau (nested loop). Mỗi lần vòng ngoài chạy một vòng, vòng trong sẽ chạy hết toàn bộ số lần của nó.

Logo Scratch
Vòng lặp lồng nhau thường dùng để vẽ hình, tạo lưới ô hoặc sinh nhiều đối tượng theo hàng và cột
📌 Ví dụ: Vẽ bảng ô 3×3
  1. Vòng ngoài: lặp lại 3 — mỗi lần đại diện một hàng.
  2. Vòng trong: lặp lại 3 — mỗi lần vẽ một ô.
  3. Sau mỗi ô: tiến và vẽ; sau mỗi hàng: quay về đầu hàng và hạ xuống.

Tổng cộng vòng trong chạy 3 × 3 = 9 lần. Đây là ý tưởng cơ bản của thuật toán lồng nhau.

⚠️ Cẩn thận

Vòng lặp lồng nhau tốn nhiều thời gian hơn. Lặp 10 bên ngoài × 10 bên trong = 100 lần thực thi. Nếu mỗi vòng còn chứa khối nặng (kiểm tra màu, hiệu ứng đồ họa…), dự án dễ bị giật.

Biến đếm và điều khiển vòng lặp

Biến (variable) là "hộp nhớ" giúp vòng lặp theo dõi tiến trình. Hai cách dùng phổ biến:

đặt [i v] thành [1]
lặp đến khi <(i) > [10]>
  đổi hiệu ứng [độ sáng v] thêm [10]
  thay đổi [i v] thêm [1]
kết thúc
📌 Ví dụ: Tìm số đầu tiên chia hết cho 7

Đặt i = 1. Lặp đến khi phần dư của (i) chia (7) = 0. Mỗi vòng tăng i thêm 1. Khi dừng, i chính là số cần tìm (bằng 7). Không cần thử tay từng số một.

Tối ưu thuật toán đơn giản là gì?

Hai chương trình cùng cho kết quả nhưng một bên chạy nhanh, một bên chậm — sự khác biệt nằm ở cách sắp xếp bước làm việc. Scratch là ngôn ngữ thông dịch, mỗi khối lệnh đều tốn thời gian xử lý; vì vậy càng ít thao tác thừa, dự án càng mượt.

Nguyên tắc 1: Đừng tính lại điều đã biết

Nếu một giá trị không đổi trong suốt vòng lặp, hãy tính nó trước rồi lưu vào biến, thay vì gọi khối tính toán phức tạp mỗi vòng.

❌ Chưa tối ưu Mỗi vòng lặp đều tính lại cos của 30 rồi mới dùng — lãng phí vì 30 không đổi.
✅ Đã tối ưu Tính cos một lần, gán vào biến giá trị, rồi trong vòng lặp chỉ đọc biến đó.

Nguyên tắc 2: Tránh khối "nặng" trong vòng lặp

Một số khối kiểm tra môi trường rất tốn sức khi gọi hàng trăm lần mỗi giây:

💡 Ghi nhớ

Hãy tự hỏi: "Việc này có thật sự cần kiểm tra mỗi khung hình không?" Nếu chỉ cần biết khi nhân vật di chuyển, hãy đặt kiểm tra sau khối di chuyển, không phải trong vòng forever rỗng chạy hàng nghìn lần.

Nguyên tắc 3: Chọn đúng loại vòng lặp

❌ Thừa Dùng forever + biến đếm + nếu thì dừng tất cả để lặp đúng 20 lần.
✅ Gọn hơn Dùng lặp lại 20 hoặc lặp đến khi đếm = 20 — dễ đọc và ít lỗi hơn.

Tăng tốc khi cần xử lý nhiều vòng lặp

Scratch mặc định chạy khoảng 30 khung hình/giây. Giữa các vòng lặp còn có độ trễ nhỏ để màn hình kịp cập nhật — điều này tốt cho animation nhưng chậm khi bạn cần tính toán hàng nghìn lần.

Chế độ Turbo

Nhấn Shift + cờ xanh (hoặc bật Turbo Mode trong menu) để Scratch bỏ độ trễ giữa các vòng lặp. Phù hợp khi vẽ hình toán học hoặc mô phỏng cần nhiều vòng repeat liên tiếp.

Chạy không làm mới màn hình (Run without screen refresh)

Khi tạo My Block (khối tùy chỉnh), bạn có thể bật tùy chọn Run without screen refresh. Toàn bộ lệnh trong khối sẽ chạy liền mạch, chỉ vẽ lại màn hình một lần ở cuối — rất hữu ích cho vòng lặp lớn bên trong khối tùy chỉnh.

My Blocks trong Scratch
Tùy chọn "Run without screen refresh" nằm khi tạo hoặc sửa khối My Blocks
📌 Ví dụ: Vẽ 360 đường thẳng tỏa tia

Tạo khối vẽ_tia với tùy chọn không làm mới màn hình. Bên trong: lặp lại 360 — quay 1 độ, bút xuống, tiến, bút lên. Gọi khối một lần sẽ vẽ xong cả hình mà không bị giật từng đường.

💡 Ghi nhớ

Turbo và "không làm mới màn hình" chỉ giúp chạy nhanh hơn, không thay thế việc viết thuật toán gọn. Một vòng lặp 10 000 lần với khối chạm màu vẫn chậm dù bật Turbo.

Mẹo thực hành và lỗi thường gặp

Vòng lặp vô hạn vô tình

Điều kiện trong repeat until không bao giờ đúng → Scratch lặp mãi. Luôn kiểm tra: biến đếm có được thay đổi bên trong vòng không? Điều kiện có thể đạt được không?

Quên khởi tạo biến

Biến i chưa được đặt giá trị ban đầu có thể gây hành vi lạ. Trước vòng lặp, hãy luôn đặt biến về giá trị xuất phát.

Lồng quá nhiều tầng

3 vòng lặp lồng nhau (10×10×10 = 1000 lần) có thể chấp nhận được; nhưng thêm khối kiểm tra phức tạp vào mỗi lần lặp sẽ khiến dự án đơ giản trông như "treo máy".

⚠️ Lỗi phổ biến

Đặt khối đợi … giây bên trong forever rồi thắc mắc vì sao game phản hồi chậm — mỗi vòng phải chờ thêm thời gian chờ đó. Chỉ dùng đợi khi thật sự cần tạo nhịp (animation, đếm ngược).

  1. Viết thuật toán bằng lời trước khi kéo khối — giúp chọn đúng loại vòng lặp.
  2. Test với số lần lặp nhỏ (3–5) trước, rồi mới tăng lên.
  3. Dùng khối nói hoặc hiển thị biến để theo dõi giá trị trong từng vòng.
  4. Sau khi chạy đúng, quay lại tối ưu: bỏ tính toán thừa, gom logic vào My Block.

Dự án thực hành: Máy tìm số nguyên tố đơn giản

Thử xây dựng chương trình nhận một số n (ví dụ 97) và kiểm tra xem n có phải số nguyên tố không — áp dụng repeat until và biến đếm.

📌 Gợi ý thuật toán
  1. Đặt i = 2 (bắt đầu thử từ 2).
  2. Lặp đến khi i × i > n (chỉ cần thử đến căn bậc hai của n).
  3. Mỗi vòng: nếu phần dư của (n) chia (i) = 0 → n không nguyên tố, dừng và báo kết quả.
  4. Tăng i thêm 1.
  5. Hết vòng lặp mà không chia hết → n là số nguyên tố.

Đây là ví dụ tối ưu đơn giản: thay vì thử mọi số từ 2 đến n−1 (rất nhiều vòng), ta chỉ thử đến khi i² > n, giảm số lần lặp đáng kể với số lớn.

💡 Ghi nhớ

Thuật toán tốt không chỉ "chạy được" mà còn "chạy ít bước hơn". Khi làm bài kiểm tra hoặc thi học sinh giỏi Tin, khả năng giải thích vì sao bạn dừng sớm là điểm cộng quan trọng.